#include "zen_gles3.h"
#include "zen_gles3_kit.h"

#pragma comment(lib, "libEGL.lib")
#pragma comment(lib, "libGLESv2.lib")

#include "zen_egl.h"

#include "zen_app_windows.h"

#include "gles3/gl3.h"

#include "zen_game_activity.h"
#include "zen_game_figure.h"
#include "zen_game_action.h"
#include "zen_game_scene.h"
#include "zen_game_sprite.h"
#include "zen_game_label.h"
#include "zen_game_dust.h"
#include "zen_file.h"

#include "zen_random.h"

class AppD : public Zen::Game::ActivityDelegate
{
	Zen::GL::Window* glWin{};

	std::shared_ptr<Zen::Game::Node> mScene;
	Zen::Random mR;

	std::shared_ptr<Zen::Game::TextureCache> mTC;

public:
	void loadScene()
	{
		auto act = Zen::Game::Activity::Only();
		auto scene = act->GetRoot()->CreateInnerNode<Zen::Game::Scene>();
		scene->GetCamera()->Orthogonal(act->GetScreenSize());
		mScene = scene;
	}
	void initActivity()
	{
		auto engine = Zen::Graphics::Engine::GLES();
		Zen::GL::Render::CullFace(Zen::GL::EFace::None);
		engine->SetClearColor(Zen::EColor::Blue);
		engine->SetClockwiseAsFront(false);
		Zen::Game::Activity::Only()->SetGraphicsEngine(engine);
	}
	void initCache()
	{
		auto act = Zen::Game::Activity::Only();

		mTC = std::make_shared<Zen::Game::TextureCache>(act->GetGraphicsEngine());

		mTC->AddImage("tex0", Zen::Game::BuiltinImages::Only()->CreateCircleTexture(Zen::EPixel::RGBA, 128));
	}
	virtual void OnLaunch()
	{
		initActivity();
		initCache();

		loadScene();

		//for (int i = 0; i < 5000; ++i)
		//{
		//	loadNode();
		//}
		//loadPoints();
		loadLabel();
		loadDust();
	}
	void loadDust()
	{
		auto bar = mTC->Get("bar.png");
		auto node = mScene->CreateInnerNode<Zen::Game::Dust>();
		node->SetTexture(bar);
		node->SetEmitorLife(100);
		node->SetDustCount(200);
		Zen::Game::GravityDustConfig config;
		//config.
		node->SetEmitor(std::make_shared<Zen::Game::GravityDustEmitor>(config));
		node->SetSize({ 1, 1 });
		node->SetPosition({ 300, 300 });
	}
	void loadPoints()
	{
		auto bar = mTC->Get("bar.png");
		auto node = mScene->CreateInnerNode<Zen::Game::FigurePointTexture>();
		node->SetTexture(bar);
		std::vector<Zen::Point2> verts;
		std::vector<float> sizes;
		std::vector<Zen::Color4f> colors;
		for (int i = 0; i < 5000; ++i)
		{
			verts.push_back({ mR.NextF<float>(), mR.NextF<float>() });
			sizes.push_back(mR.NextF<float>(100));
			auto color = Zen::Color4b(mR.Next());
			color.a8 = 255;
			colors.push_back(color);
		}
		node->SetColor(Zen::EColor::White);
		node->SetPolygon(verts);
		node->SetColors(colors);
		node->SetPointSizes(sizes);
		auto act = Zen::Game::Activity::Only();
		node->SetSize(act->GetScreenSize());
	}

	void loadLabel()
	{
		auto act = Zen::Game::Activity::Only();
		auto vs = act->GetScreenSize();

		auto font = Zen::Font::Generate(Zen::LoadFileToBuffer("D:/Fonts/arial.ttf"));
		auto brush = Zen::FontBrush::Generate(font, 32);
		auto textr = std::make_shared<Zen::Game::DefaultTextRender>(brush);

		auto node = mScene->CreateInnerNode<Zen::Game::TextLabel>();
		node->SetTextRender(textr);
		node->SetFontSize(52);
		node->SetText("hello");
		node->SetPosition({ 50, 50 });
		node->SetColor(Zen::EColor::Red);
		node->SetBlend(Zen::Graphics::EBlend::Normal);
		node->SetFlipX(true);
		node->SetFlipY(true);
		auto action = Zen::Game::ActionCall::Generate(
			[node](float delay, int) {
				node->SetText("fps:" + std::to_string(Zen::Game::Activity::Only()->GetRealFPS()));
				return true;
			},
			0, 0, 2.f);
		Zen::Game::Activity::Only()->GetActionDispather()->RunAction(action, node);
	}

	virtual void loadNode()
	{
		auto act = Zen::Game::Activity::Only();
		auto vs = act->GetScreenSize();

		auto node = mScene->CreateInnerNode<Zen::Game::Sprite>();
		//auto node = act->GetRoot()->CreateInnerNode<Zen::Game::FigureTexture>();
		//node->SetPolygon({ { -0.5f, 0 }, { 0.5f, -0.5f }, { 0.5f, 0.5f }, { 0, 1 } }, { Zen::EColor::Black, Zen::EColor::Blue, Zen::EColor::Red, Zen::EColor::White });

		auto bar = mTC->Get("bar.png");
		node->SetTexture(bar, { 0, 0, 1.0, 1.0 });
		node->SetColor(Zen::Color4b(mR.Next()));
		node->SetBlend(Zen::Graphics::EBlend::Normal);
		node->SetObjectName("node");
		auto s = (float)mR.Next(100);
		node->SetSize({ s, s });
		node->SetPosition({ mR.NextF(vs.x), mR.NextF(vs.y) });

		node->SetDrawMode(Zen::Graphics::EDrawMode::TriangleStrip);
		auto action = Zen::Game::ActionCall::Generate(
			[node](float interval, int n) {
				node->SetRotation(node->GetRotation() + interval);
				return true;
			},
			-1, 0.f, 0.f);
		act->GetActionDispather()->RunAction(action, node);
		action->SetObjectName("action");

		auto touch = std::make_shared<Zen::Game::DefaultTouchHandle>();
		touch->SetObjectName("touch");
		touch->TouchDownCallback() = [act, node](Zen::AppTouch const& touch) mutable -> bool {
			std::cout << "touch down" << std::endl;
			//act->GetTouchDispatcher()->RemoveTouchHandleOnNode(node);
			node->ReleaseSelf();
			return true;
		};
		act->GetTouchDispatcher()->AddTouchHandle(touch, 0, node, true);
	}

	virtual void OnResize() {}

	virtual void OnPause() {}

	virtual void OnResume() {}

	virtual void OnExit() {}

	virtual void OnEvent(std::string event) {}
};

std::shared_ptr<Zen::AppDelegate> ZenAppMain(Zen::AppConfig* config)
{
	config->WindowHeight = 800;
	config->WindowWidth = 800;
	config->FramesPerSecond = 60.f;
	config->Title = "I";

	Zen::Game::Activity::Only()->SetDelegate(std::make_shared<AppD>());

	return Zen::Game::Activity::Only();
}
